home *** CD-ROM | disk | FTP | other *** search
- ╒═══════════════════════════════╕
- │ W E L C O M E │
- │ To the VGA Trainer Program │ │
- │ By │ │
- │ DENTHOR of ASPHYXIA │ │ │
- ╘═══════════════════════════════╛ │ │
- ────────────────────────────────┘ │
- ────────────────────────────────┘
-
- --==[ PART 10 ]==--
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Introduction
-
- Wow! The trainer has finally reached part 10! This will also be the
- first part introduced simultaneously to local BBS's and the INTERNET at
- the same time! Yes folks, I put up a copy of previous tutorials onto
- various ftp sites, and awaited the flames saying that the net.gurus
- already knew this stuff, and why was I wasting disk space! The flames
- did not appear (well, except for one), and I got some messages saying
- keep it up, so from now on I will upload all future trainers to ftp
- sites too (wasp.eng.ufl.edu , cs.uwp.edu etc.). I will also leave a
- notice in the USENET groups comp.lang.pascal and comp.sys.ibm.pc.demos
- when a new part is finished (Until enough people say stop ;-))
-
- I can also be reached at my new E-Mail address,
- smith9@batis.bis.und.ac.za
-
- Well, this tutorial is on Chain-4. When asked to do a trainer on
- Chain-4, I felt that I would be walking on much travelled ground (I have
- seen numerous trainers on the subject), but the people who asked me said
- that they hadn't seen any, so could I do one anyway? Who am I to say no?
-
- The sample program attached isn't that great, but I am sure that all you
- people out there can immediately see the potential that Chain-4 holds.
-
-
- If you would like to contact me, or the team, there are many ways you
- can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
- on the ASPHYXIA BBS.
- 2) Write to Denthor, EzE or Goth on Connectix.
- 3) Write to : Grant Smith
- P.O.Box 270 Kloof
- 3640
- Natal
- South Africa
- 4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
- call during varsity). Call +27-31-73-2129 if you call
- from outside South Africa. (It's YOUR phone bill ;-))
- 5) Write to smith9@batis.bis.und.ac.za in E-Mail.
-
- NB : If you are a representative of a company or BBS, and want ASPHYXIA
- to do you a demo, leave mail to me; we can discuss it.
- NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
- quite lonely and want to meet/help out/exchange code with other demo
- groups. What do you have to lose? Leave a message here and we can work
- out how to transfer it. We really want to hear from you!
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ What is Chain-4?
-
- You people out there all have at least 256k vga cards. Most of you have
- 512k vga cards, and some have 1MB vga cards. But what you see on your
- screen, as discussed in previous trainers, is 64k of data! What happened
- to the other 192k??? Chain-4 is a method of using all 256k at one time.
-
- The way this is done is simple. 1 screen = 64k. 64k * 4 = 256k.
- Therefore, chain-4 allows you to write to four screens, while displaying
- one of them. You can then move around these four screens to see the data
- on them. Think of the Chain-4 screen as a big canvas. The viewport,
- the bit you see out of, is a smaller rectangle which can be anywhere
- over the bigger canvas.
-
- +----------------------------+ Chain-4 screen
- | +--+ |
- | | | <- Viewport |
- | +--+ |
- | |
- +----------------------------+
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ The size of the chain-4 screen
-
- The Chain-4 screen, can be any size that adds up to 4 screens.
-
- For example, it can be 4 screens across and one screen down, or one
- screen across and 4 screens down, or two screens across and two screens
- down, and any size in between.
-
- In the sample program, the size is a constant. The size * 8 is how many
- pixels across there are on the chain-4 screen, ie
- Size = 40 = 320 pixels across = 1 screen across, 4 screens down
- Size = 80 = 640 pixels across = 2 screens across, 2 screens down
- etc.
-
- We need to know the size of the screen for almost all dealings with the
- Chain-4 screen, for obvious reasons.
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Layout of the chain-4 screen, and accessing it
-
- If you will remember all the way back to Part 1 of this series, I
- explained that the memory layout of the MCGA screen is linear. Ie, the
- top left hand pixel was pixel zero, the one to the right of it was
- number one, the next one was number two etc. With Chain-4, things are
- very different.
-
- Chain-4 gets the 4 screens and chains them together (hence the name :)).
- Each screen has a different plane value, and must be accessed
- differently. The reason for this is that a segment of memory is only 64k
- big, so that we could not fit the entire Chain-4 screen into one
- segment.
-
- All Chain-4 screens are accessed from $a000, just like in MCGA mode.
- What we do is, before we write to the screen, find out what plane we are
- writing to, set that plane, then plot the pixel. Here is how we find out
- how far in to plot the pixel and what plane it is on :
-
- Instead of the linear model of MCGA mode, ie :
- ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
- │00│01│02│03│04│05│06│07│08│09│10│11│ ...
-
- Each plane of the Chain-4 screen accesses the memory in this way :
-
- Plane 0 :
- ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
- │00│ │ │ │01│ │ │ │02│ │ │ │ ...
-
- Plane 1 :
- ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
- │ │00│ │ │ │01│ │ │ │02│ │ │ ...
-
- Plane 2 :
- ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
- │ │ │00│ │ │ │01│ │ │ │02│ │ ...
-
- Plane 3 :
- ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
- │ │ │ │00│ │ │ │01│ │ │ │02│ ...
-
- In this way, by choosing the right plane to write to, we can access all
- of the 256k of memory available to us. The plane that we write to can
- easily be found by the simple calculation of x mod 4, and the x
- coordinate is also found by x div 4. We work out our y by multiplying
- it by the size of our chain-4 screen.
-
- NOTE : It is possible to write to all four planes at once by setting the
- correct port values.
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Uses of Chain-4
-
- The uses of Chain-4 are many. One could write data to one screen, then
- flip to it (the move_to command is almost instantaneous). This means
- that 64k of memory does not need to be set aside for a virtual screen,
- you are using the vga cards memory instead!
-
- Scrolling is much easier to code for in Chain-4 mode.
-
- It is possible to "tweak" the mode into other resolutions. In our demo,
- our vectors were in 320x240 mode, and our dot vectors were in 320x400
- mode.
-
- The main disadvantage of chain-4 as I see it is the plane swapping,
- which can be slow. With a bit of clever coding however, these can be
- kept down to a minimum.
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ The sample programs
-
- The first sample program is GFX.PAS. This is a until in which I have
- placed most of our routines from previous tuts. All the procedures and
- variables you can see under the INTERFACE section can be used in any
- program with GFX in the USES clause. In other words, I could do this :
-
- USES GFX,crt;
-
- BEGIN
- Setupvirtual;
- cls (vaddr,0);
- Shutdown;
- END.
-
- This program would compile perfectly. What I suggest you do is this :
- Rename the file to a name that suites you (eg your group name), change
- the first line of the unit to that name, then add all useful procedures
- etc. to the unit. Make it grow :-).
-
- The second file is the sample program (note the USES GFX,crt; up near
- the top!). The program is easy to understand and is documented. The bit
- that I want to draw your attention to is the constant, BIT. Because I
- am distributing this file to many places in text form, not binary form,
- I could not just add a .CEL file with the program. So what I did was
- write some text in one color then saved it as a .CEL . I then wrote a
- ten line program that did the following : Moving from left to right, it
- counted how many pixels were of color zero, then saved the byte value to
- an array. When it came across color one, is counted for how long that
- went on then saved the byte value and saved it to an array and so on.
- When it was finished, I converted the array into a text file in the
- CONST format. Not too cunning, but I thought I had better explain it ;-)
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ In closing
-
- There are other documents and sample programs available on Chain-4 and
- it's like : Try XLIB for one...
-
- Finally! Some BBS's have joined my BBS list! (Okay, only two new ones,
- but it's a start ;-)) All you international BBS's! If you will regularly
- download the tuts from an FTP site, give me your names!
-
- I own a car. The car's name is Bob. A few days ago, Bob was in an
- accident, and now has major damage to his front. Knowing insurance, I
- probably won't get much, probably nothing (the other guy wasn't insured,
- and I am only 18 :( ). I will probably have to find work in order to pay
- for my repairs. The point to this meandering is this : I am upset, so if
- you think you are getting a quote, you can just forget it.
-
- Oh, well. Life goes on!
-
- See you next time,
- - Denthor
-
- These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
-
- ╔══════════════════════════╦════════════════╦═════╦═══╦════╦════╗
- ║BBS Name ║Telephone No. ║Open ║Msg║File║Past║
- ╠══════════════════════════╬════════════════╬═════╬═══╬════╬════╣
- ║ASPHYXIA BBS #1 ║(031) 765-5312 ║ALL ║ * ║ * ║ * ║
- ║ASPHYXIA BBS #2 ║(031) 765-6293 ║ALL ║ * ║ * ║ * ║
- ║Connectix BBS ║(031) 266-9992 ║ALL ║ ║ * ║ * ║
- ║POP! ║(012) 661-1257 ║ALL ║ ║ * ║ * ║
- ║Pure Surf BBS ║(031) 561-5943 ║A/H ║ ║ * ║ * ║
- ╚══════════════════════════╩════════════════╩═════╩═══╩════╩════╝
-
- For international users : If you live outside the Republic of South
- Africa, do the following : Dial +27, dont dial the first 0, but dial
- the rest of the number. Eg, for the ASPHYXIA BBS : +27-31-765-5312
-
- Open = Open at all times or only A/H
- Msg = Available in message base
- File = Available in file base
- Past = Previous Parts available
-
- Unit GFX;
-
-
- INTERFACE
-
- USES crt;
- CONST VGA = $A000;
-
- TYPE Virtual = Array [1..64000] of byte; { The size of our Virtual Screen }
- VirtPtr = ^Virtual; { Pointer to the virtual screen }
-
- VAR Virscr : VirtPtr; { Our first Virtual screen }
- Vaddr : word; { The segment of our virtual screen}
-
- Procedure SetMCGA;
- { This procedure gets you into 320x200x256 mode. }
- Procedure SetText;
- { This procedure returns you to text mode. }
- Procedure Cls (Where:word;Col : Byte);
- { This clears the screen to the specified color }
- Procedure SetUpVirtual;
- { This sets up the memory needed for the virtual screen }
- Procedure ShutDown;
- { This frees the memory used by the virtual screen }
- procedure flip(source,dest:Word);
- { This copies the entire screen at "source" to destination }
- Procedure Pal(Col,R,G,B : Byte);
- { This sets the Red, Green and Blue values of a certain color }
- Procedure GetPal(Col : Byte; Var R,G,B : Byte);
- { This gets the Red, Green and Blue values of a certain color }
- procedure WaitRetrace;
- { This waits for a vertical retrace to reduce snow on the screen }
- Procedure Hline (x1,x2,y:word;col:byte;where:word);
- { This draws a horizontal line from x1 to x2 on line y in color col }
- Procedure Line(a,b,c,d:integer;col:byte;where:word);
- { This draws a solid line from a,b to c,d in colour col }
- Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
- { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
- in color col }
- Function rad (theta : real) : real;
- { This calculates the degrees of an angle }
- Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
- { This puts a pixel on the screen by writing directly to memory. }
- Function Getpixel (X,Y : Integer; where:word) :Byte;
- { This gets the pixel on the screen by reading directly to memory. }
-
-
- IMPLEMENTATION
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure SetMCGA; { This procedure gets you into 320x200x256 mode. }
- BEGIN
- asm
- mov ax,0013h
- int 10h
- end;
- END;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure SetText; { This procedure returns you to text mode. }
- BEGIN
- asm
- mov ax,0003h
- int 10h
- end;
- END;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Cls (Where:word;Col : Byte); assembler;
- { This clears the screen to the specified color }
- asm
- push es
- mov cx, 32000;
- mov es,[where]
- xor di,di
- mov al,[col]
- mov ah,al
- rep stosw
- pop es
- End;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure SetUpVirtual;
- { This sets up the memory needed for the virtual screen }
- BEGIN
- GetMem (VirScr,64000);
- vaddr := seg (virscr^);
- END;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure ShutDown;
- { This frees the memory used by the virtual screen }
- BEGIN
- FreeMem (VirScr,64000);
- END;
-
- {──────────────────────────────────────────────────────────────────────────}
- procedure flip(source,dest:Word); assembler;
- { This copies the entire screen at "source" to destination }
- asm
- push ds
- mov ax, [Dest]
- mov es, ax
- mov ax, [Source]
- mov ds, ax
- xor si, si
- xor di, di
- mov cx, 32000
- rep movsw
- pop ds
- end;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Pal(Col,R,G,B : Byte); assembler;
- { This sets the Red, Green and Blue values of a certain color }
- asm
- mov dx,3c8h
- mov al,[col]
- out dx,al
- inc dx
- mov al,[r]
- out dx,al
- mov al,[g]
- out dx,al
- mov al,[b]
- out dx,al
- end;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure GetPal(Col : Byte; Var R,G,B : Byte);
- { This gets the Red, Green and Blue values of a certain color }
- Var
- rr,gg,bb : Byte;
- Begin
- asm
- mov dx,3c7h
- mov al,col
- out dx,al
-
- add dx,2
-
- in al,dx
- mov [rr],al
- in al,dx
- mov [gg],al
- in al,dx
- mov [bb],al
- end;
- r := rr;
- g := gg;
- b := bb;
- end;
-
- {──────────────────────────────────────────────────────────────────────────}
- procedure WaitRetrace; assembler;
- { This waits for a vertical retrace to reduce snow on the screen }
- label
- l1, l2;
- asm
- mov dx,3DAh
- l1:
- in al,dx
- and al,08h
- jnz l1
- l2:
- in al,dx
- and al,08h
- jz l2
- end;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
- { This draws a horizontal line from x1 to x2 on line y in color col }
- asm
- mov ax,where
- mov es,ax
- mov ax,y
- mov di,ax
- shl ax,8
- shl di,6
- add di,ax
- add di,x1
-
- mov al,col
- mov ah,al
- mov cx,x2
- sub cx,x1
- shr cx,1
- jnc @start
- stosb
- @Start :
- rep stosw
- end;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Line(a,b,c,d:integer;col:byte;where:word);
- { This draws a solid line from a,b to c,d in colour col }
- function sgn(a:real):integer;
- begin
- if a>0 then sgn:=+1;
- if a<0 then sgn:=-1;
- if a=0 then sgn:=0;
- end;
- var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
- begin
- u:= c - a;
- v:= d - b;
- d1x:= SGN(u);
- d1y:= SGN(v);
- d2x:= SGN(u);
- d2y:= 0;
- m:= ABS(u);
- n := ABS(v);
- IF NOT (M>N) then
- BEGIN
- d2x := 0 ;
- d2y := SGN(v);
- m := ABS(v);
- n := ABS(u);
- END;
- s := m shr 1;
- FOR i := 0 TO m DO
- BEGIN
- putpixel(a,b,col,where);
- s := s + n;
- IF not (s<m) THEN
- BEGIN
- s := s - m;
- a:= a + d1x;
- b := b + d1y;
- END
- ELSE
- BEGIN
- a := a + d2x;
- b := b + d2y;
- END;
- end;
- END;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
- { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
- in color col }
- var
- x:integer;
- mny,mxy:integer;
- mnx,mxx,yc:integer;
- mul1,div1,
- mul2,div2,
- mul3,div3,
- mul4,div4:integer;
-
- begin
- mny:=y1; mxy:=y1;
- if y2<mny then mny:=y2;
- if y2>mxy then mxy:=y2;
- if y3<mny then mny:=y3;
- if y3>mxy then mxy:=y3; { Choose the min y mny and max y mxy }
- if y4<mny then mny:=y4;
- if y4>mxy then mxy:=y4;
-
- if mny<0 then mny:=0;
- if mxy>199 then mxy:=199;
- if mny>199 then exit;
- if mxy<0 then exit; { Verticle range checking }
-
- mul1:=x1-x4; div1:=y1-y4;
- mul2:=x2-x1; div2:=y2-y1;
- mul3:=x3-x2; div3:=y3-y2;
- mul4:=x4-x3; div4:=y4-y3; { Constansts needed for intersection calc }
-
- for yc:=mny to mxy do
- begin
- mnx:=320;
- mxx:=-1;
- if (y4>=yc) or (y1>=yc) then
- if (y4<=yc) or (y1<=yc) then { Check that yc is between y1 and y4 }
- if not(y4=y1) then
- begin
- x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
- if x<mnx then
- mnx:=x;
- if x>mxx then
- mxx:=x; { Set point as start or end of horiz line }
- end;
- if (y1>=yc) or (y2>=yc) then
- if (y1<=yc) or (y2<=yc) then { Check that yc is between y1 and y2 }
- if not(y1=y2) then
- begin
- x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
- if x<mnx then
- mnx:=x;
- if x>mxx then
- mxx:=x; { Set point as start or end of horiz line }
- end;
- if (y2>=yc) or (y3>=yc) then
- if (y2<=yc) or (y3<=yc) then { Check that yc is between y2 and y3 }
- if not(y2=y3) then
- begin
- x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
- if x<mnx then
- mnx:=x;
- if x>mxx then
- mxx:=x; { Set point as start or end of horiz line }
- end;
- if (y3>=yc) or (y4>=yc) then
- if (y3<=yc) or (y4<=yc) then { Check that yc is between y3 and y4 }
- if not(y3=y4) then
- begin
- x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
- if x<mnx then
- mnx:=x;
- if x>mxx then
- mxx:=x; { Set point as start or end of horiz line }
- end;
- if mnx<0 then
- mnx:=0;
- if mxx>319 then
- mxx:=319; { Range checking on horizontal line }
- if mnx<=mxx then
- hline (mnx,mxx,yc,color,where); { Draw the horizontal line }
- end;
- end;
-
- {──────────────────────────────────────────────────────────────────────────}
- Function rad (theta : real) : real;
- { This calculates the degrees of an angle }
- BEGIN
- rad := theta * pi / 180
- END;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
- { This puts a pixel on the screen by writing directly to memory. }
- Asm
- mov ax,[where]
- mov es,ax
- mov bx,[X]
- mov dx,[Y]
- mov di,bx
- mov bx, dx {; bx = dx}
- shl dx, 8
- shl bx, 6
- add dx, bx {; dx = dx + bx (ie y*320)}
- add di, dx {; finalise location}
- mov al, [Col]
- stosb
- End;
-
- {──────────────────────────────────────────────────────────────────────────}
- Function Getpixel (X,Y : Integer; where:word):byte; assembler;
- { This puts a pixel on the screen by writing directly to memory. }
- Asm
- mov ax,[where]
- mov es,ax
- mov bx,[X]
- mov dx,[Y]
- mov di,bx
- mov bx, dx {; bx = dx}
- shl dx, 8
- shl bx, 6
- add dx, bx {; dx = dx + bx (ie y*320)}
- add di, dx {; finalise location}
- lodsb
- End;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure LoadCEL (FileName : string; ScrPtr : pointer);
- { This loads the cel 'filename' into the pointer scrptr }
- var
- Fil : file;
- Buf : array [1..1024] of byte;
- BlocksRead, Count : word;
- begin
- assign (Fil, FileName);
- reset (Fil, 1);
- BlockRead (Fil, Buf, 800); { Read and ignore the 800 byte header }
- Count := 0; BlocksRead := $FFFF;
- while (not eof (Fil)) and (BlocksRead <> 0) do begin
- BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
- Count := Count + 1024;
- end;
- close (Fil);
- end;
-
-
- BEGIN
- END.Uses Crt,GFX;
-
- Const Size : Byte = 80; { Size = 40 = 1 across, 4 down }
- { Size = 80 = 2 across, 2 down }
- { Size = 160 = 4 across, 1 down }
-
- bit : Array [1..897] of byte = (
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,2,151,5,149,6,148,7,147,8,49,2,95,8,49,
- 4,93,9,49,3,93,4,2,3,49,4,92,4,3,3,48,4,92,4,3,4,48,4,91,4,4,3,48,4,92,4,3,4,
- 48,3,58,2,32,4,4,4,47,4,57,3,31,4,5,3,48,3,57,4,30,4,5,4,47,3,57,5,29,4,6,4,46,
- 4,57,4,29,4,7,3,47,3,58,2,30,4,7,4,46,4,90,4,7,4,46,3,90,4,8,4,27,2,16,3,90,4,
- 8,9,22,3,16,3,89,4,5,13,8,6,8,3,15,3,90,4,2,15,6,10,6,3,16,3,6,1,21,1,9,2,7,1,
- 21,6,14,18,9,5,2,4,5,4,1,4,10,3,4,5,10,2,7,3,8,2,5,3,9,3,7,8,13,13,1,4,9,4,5,3,
- 5,3,1,6,9,3,3,6,9,4,5,4,8,3,3,4,9,3,6,9,11,10,6,4,8,4,6,3,4,11,8,3,2,7,9,5,4,4,
- 9,3,2,4,9,3,6,4,4,2,8,10,9,4,7,4,6,3,5,5,3,3,8,3,1,8,8,5,4,5,8,3,3,3,9,4,5,4,5,
- 2,5,10,12,4,7,3,5,5,4,5,4,3,7,3,1,4,1,3,9,4,5,4,9,3,2,3,10,3,6,3,5,3,4,10,13,3,
- 8,3,2,7,5,4,5,3,7,7,1,3,9,4,5,5,9,3,1,3,10,3,6,3,5,4,4,5,1,4,12,4,8,3,2,5,6,4,
- 5,4,6,6,2,4,8,4,5,5,10,6,10,4,5,4,5,3,5,2,3,4,13,4,8,3,3,1,9,3,6,3,7,5,3,3,5,1,
- 3,3,5,5,4,2,5,5,11,3,6,3,5,4,10,3,14,4,8,3,12,3,6,4,6,5,3,3,5,2,2,4,4,6,4,2,5,
- 5,6,1,3,4,5,3,6,3,10,4,14,4,5,1,2,4,11,3,6,3,7,5,3,3,4,3,1,4,4,6,4,3,5,4,6,2,3,
- 3,6,3,5,4,9,4,15,3,5,2,3,4,9,3,6,4,7,4,3,3,5,2,2,3,4,7,3,3,6,3,6,3,2,4,5,4,5,3,
- 10,3,15,4,4,3,4,3,9,3,6,3,7,4,4,3,4,3,1,4,3,3,1,3,3,3,6,4,6,2,3,3,6,3,5,4,9,4,
- 15,4,4,3,4,4,7,3,6,4,7,4,3,3,4,3,2,3,3,3,2,3,2,4,5,5,5,3,2,4,6,3,5,4,8,4,16,4,
- 4,2,6,3,7,3,5,4,7,4,4,3,3,3,3,8,2,3,2,4,5,6,4,3,3,3,7,3,4,5,8,4,16,4,4,2,6,3,6,
- 3,5,4,8,3,5,8,3,9,2,3,1,4,6,6,3,3,4,3,7,3,3,6,7,4,17,4,4,3,5,3,6,3,4,4,9,3,5,8,
- 3,7,3,8,6,3,1,4,1,4,3,4,7,3,2,3,1,3,7,4,17,4,4,3,5,3,5,11,9,3,6,7,4,6,4,7,6,3,
- 2,8,4,3,8,7,2,3,6,4,18,3,5,4,3,4,5,10,10,3,6,6,6,4,4,6,7,3,4,6,5,3,8,7,2,4,4,4,
- 19,3,5,10,5,3,1,6,11,3,7,3,16,5,7,4,4,5,6,3,8,6,3,5,3,4,19,3,6,9,5,3,18,2,25,5,
- 9,3,6,3,7,2,10,3,6,4,3,3,20,3,8,5,6,3,44,6,10,2,39,3,3,2,22,2,19,3,43,7,101,3,
- 42,8,102,3,41,4,1,4,101,4,39,5,2,3,102,3,39,4,4,3,102,3,38,4,4,4,101,3,38,4,5,
- 3,102,3,37,4,5,4,101,4,36,4,6,3,102,3,37,3,6,4,102,3,36,4,6,3,102,3,37,3,6,3,
- 103,3,37,3,5,4,102,4,37,3,4,4,103,3,38,10,104,3,38,9,105,2,40,7,106,2,41,4,0);
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure InitChain4; ASSEMBLER;
- { This procedure gets you into Chain 4 mode }
- Asm
- mov ax, 13h
- int 10h { Get into MCGA Mode }
-
- mov dx, 3c4h { Port 3c4h = Sequencer Address Register }
- mov al, 4 { Index 4 = memory mode }
- out dx, al
- inc dx { Port 3c5h ... here we set the mem mode }
- in al, dx
- and al, not 08h
- or al, 04h
- out dx, al
- mov dx, 3ceh
- mov al, 5
- out dx, al
- inc dx
- in al, dx
- and al, not 10h
- out dx, al
- dec dx
- mov al, 6
- out dx, al
- inc dx
- in al, dx
- and al, not 02h
- out dx, al
- mov dx, 3c4h
- mov ax, (0fh shl 8) + 2
- out dx, ax
- mov ax, 0a000h
- mov es, ax
- sub di, di
- mov ax, 0000h {8080h}
- mov cx, 32768
- cld
- rep stosw { Clear garbage off the screen ... }
-
- mov dx, 3d4h
- mov al, 14h
- out dx, al
- inc dx
- in al, dx
- and al, not 40h
- out dx, al
- dec dx
- mov al, 17h
- out dx, al
- inc dx
- in al, dx
- or al, 40h
- out dx, al
-
- mov dx, 3d4h
- mov al, 13h
- out dx, al
- inc dx
- mov al, [Size] { Size * 8 = Pixels across. Only 320 are visible}
- out dx, al
- End;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure C4PutPixel(X,Y : Word; Col : Byte); ASSEMBLER;
- { This puts a pixel on the chain 4 screen }
- Asm
- mov ax,[y]
- xor bx,bx
- mov bl,[size]
- imul bx
- shl ax,1
- mov bx,ax
- mov ax, [X]
- mov cx, ax
- shr ax, 2
- add bx, ax
- and cx, 00000011b
- mov ah, 1
- shl ah, cl
- mov dx, 3c4h { Sequencer Register }
- mov al, 2 { Map Mask Index }
- out dx, ax
-
- mov ax, 0a000h
- mov es, ax
- mov al, [col]
- mov es: [bx], al
- End;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Plane(Which : Byte); ASSEMBLER;
- { This sets the plane to write to in Chain 4}
- Asm
- mov al, 2h
- mov ah, 1
- mov cl, [Which]
- shl ah, cl
- mov dx, 3c4h { Sequencer Register }
- out dx, ax
- End;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- procedure moveto(x, y : word);
- { This moves to position x*4,y on a chain 4 screen }
- var o : word;
- begin
- o := y*size*2+x;
- asm
- mov bx, [o]
- mov ah, bh
- mov al, 0ch
-
- mov dx, 3d4h
- out dx, ax
-
- mov ah, bl
- mov al, 0dh
- mov dx, 3d4h
- out dx, ax
- end;
- end;
-
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Putpic (x,y:integer);
- { This put's the picture at coordinates x,y on the chain-4 screen }
- Var loop1,loop2:integer;
- depth,cur:integer;
- BEGIN
- depth:=1;
- cur:=0;
- For loop1:=1 to 897 do BEGIN
- for loop2:=1 to bit [loop1] do BEGIN
- if cur<>0 then c4putpixel ((depth mod 155)+x,(depth div 155)+y,depth div 155);
- inc (depth);
- END;
- cur:=(cur+1) mod 2;
- END;
- END;
-
-
- Procedure Play;
- Var loop1,loop2:integer;
- xpos,ypos,xdir,ydir:integer;
- ch:char;
- Begin
- for loop1:=1 to 62 do
- pal (loop1,loop1,0,62-loop1); { This sets up the pallette for the pic }
-
- MoveTo(0,0); { This moves the view to the top left hand corner }
-
- for loop1:=0 to 3 do
- for loop2:=0 to 5 do
- putpic (loop1*160,loop2*66); { This places the picture all over the
- chain-4 screen }
- readkey;
- ch:=#0;
- xpos:=random (78)+1;
- ypos:=random (198)+1; { Random start positions for the view }
- xdir:=1;
- ydir:=1;
- repeat
- moveto (xpos,ypos);
- waitretrace; { Take this out and watch the screen go crazy! }
- xpos:=xpos+xdir;
- ypos:=ypos+ydir;
- if (xpos>79) or (xpos<1) then xdir:=-xdir;
- if (ypos>199) or (ypos<1) then ydir:=-ydir; { Hit a boundry, change
- direction! }
- if keypressed then ch:=readkey;
- until ch=#27; { Quit when escape is pressed }
- End;
-
-
- BEGIN
- clrscr;
- writeln ('Hello there! Here is the tenth tutorial, on Chain-4! You will notice');
- writeln ('that there are two pascal files here : one is a unit containing all');
- writeln ('our base graphics routines, and one is the demo program.');
- writeln;
- writeln ('In the demo program, we will do the necessary port stuff to get into');
- writeln ('Chain-4. Once in Chain-4 mode, I will put down text saying ASPHYXIA');
- writeln ('over the entire screen. After a key is pressed, the viewport will');
- writeln ('bounce around, displaying the entire Chain-4 screen. The program will');
- writeln ('end when [ESC] is pressed. The code here is really basic (except for');
- writeln ('those port values), and should be very easy to understand.');
- writeln;
- writeln;
- Write (' Hit any key to contine ...');
- Readkey;
- initChain4;
- play;
- SetText;
- Writeln ('All done. This concludes the tenth sample program in the ASPHYXIA');
- Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
- Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
- Writeln ('Connectix BBS user, and occasionally read RSAProg. E-mail me at :');
- Writeln (' smith9@batis.bis.und.ac.za');
- Writeln ('The numbers are available in the main text. You may also write to me at:');
- Writeln (' Grant Smith');
- Writeln (' P.O. Box 270');
- Writeln (' Kloof');
- Writeln (' 3640');
- Writeln (' Natal');
- Writeln (' South Africa');
- Writeln ('I hope to hear from you soon!');
- Writeln; Writeln;
- Write ('Hit any key to exit ...');
- Readkey;
- END.